"""Provides BUILD macros for MediaPipe graphs.

mediapipe_binary_graph() converts a graph from text format to serialized binary
format.

Example:
  mediapipe_binary_graph(
    name = "make_graph_binarypb",
    graph = "//mediapipe/framework/tool/testdata:test_graph",
    output_name = "test.binarypb",
    deps = [
        "//video/annotation:graph_calculators_lib",
    ]
  )

"""

load("//mediapipe/framework:encode_binary_proto.bzl", "encode_binary_proto", "generate_proto_descriptor_set")
load("//mediapipe/framework:transitive_protos.bzl", "transitive_proto_cc_libs", "transitive_proto_descriptor_sets", "transitive_protos")

def mediapipe_binary_graph(name, graph = None, output_name = None, deps = [], testonly = None, **kwargs):
    """Converts a graph from text format to binary format.

    Args:
      name: the name of the encode_binary_proto rule generated by this macro.
      graph: the BUILD label of a text-format MediaPipe graph.
      output_name: the name of the file to which the binary serialization is
          written.
      deps: the BUILD labels of dependencies that provide any additional message
          types used by the graph. The basic messages defined in calculator.proto
          are always available, but any custom types (e.g. specific calculator
          options) should be provided here. It is sufficient to provide targets
          that depend on the required protos indirectly: this macro examines the
          entire dependency tree, and does not build any dependencies except for
          the protos it finds.
      testonly: pass 1 if the graph is to be used only for tests.
      **kwargs: any other arguments valid for encode_binary_proto.
    """

    if not graph:
        fail("No input graph file specified.")

    if not output_name:
        fail("Must specify the output_name.")

    transitive_protos(
        name = name + "_gather_protos",
        deps = deps,
        testonly = testonly,
    )

    # This collects descriptor sets for tools that need them.
    transitive_proto_descriptor_sets(
        name = name + "_gather_proto_descriptor_sets",
        deps = deps,
        testonly = testonly,
    )

    # This collects the generated .a libraries for tools that need them.
    transitive_proto_cc_libs(
        name = name + "_gather_proto_libs",
        deps = deps,
        testonly = testonly,
    )

    # This generates a single descriptor set with a single invocation of the proto compiler.
    # May be faster than using the descriptor sets from proto_library.
    # We always pass at least the calculator proto since the proto compiler would fail
    # if it were passed no protos.
    generate_proto_descriptor_set(
        name = name + "_proto_descriptor_set",
        deps = [
            name + "_gather_protos",
            "//mediapipe/framework:calculator_proto",
        ],
        testonly = testonly,
    )

    return encode_binary_proto(
        name = name,
        deps = [
            name + "_gather_protos",
            "//mediapipe/framework:calculator_proto",
            "//mediapipe/framework/stream_handler:fixed_size_input_stream_handler_proto",
        ],
        message_type = "mediapipe.CalculatorGraphConfig",
        input = graph,
        output = output_name,
        testonly = testonly,
        **kwargs
    )
